package cn.moon.server.handler;

import cn.moon.common.constants.Constants;
import cn.moon.common.enums.ChannelTypeEnum;
import cn.moon.protocol.ProxyMessage;
import cn.moon.server.channel.ServerChannelManager;
import cn.moon.utils.ByteArrayUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ServiceFrameDecoder extends LengthFieldBasedFrameDecoder {

    public ServiceFrameDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength) {
        super(maxFrameLength, lengthFieldOffset, lengthFieldLength, 0, lengthFieldLength);
    }


    @Override
    public void channelInactive(ChannelHandlerContext ctx) {

        log.debug("======== [channelInactive] ========");

        // 移除接入信道
        ServerChannelManager.removePortalChannel(ctx.channel());

    }


    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {

        log.debug("======== ServiceFrameDecoder decode =======");

        Channel channel = ctx.channel();

        ChannelTypeEnum channelType = channel.attr(Constants.CHANNEL_TYPE).get();

        if(channelType == null){

            if(in.readableBytes() < Constants.NPXY_HEADER.length){
                return null;
            }

            byte[] bytes = new byte[Constants.NPXY_HEADER.length];
            in.readBytes(bytes);

            if(ByteArrayUtils.equals(Constants.NPXY_HEADER, bytes)){
                channelType = ChannelTypeEnum.BRIDGE;
            }else {
                channelType = ChannelTypeEnum.PORTAL;
                in.readerIndex(in.readerIndex() - Constants.NPXY_HEADER.length);
                ServerChannelManager.addPortalChannel(channel);
            }
        }

        ctx.channel().attr(Constants.CHANNEL_TYPE).set(channelType);

        if (ChannelTypeEnum.BRIDGE.equals(channelType)){
            return super.decode(ctx, in);
        }

        byte[] content = new byte[in.readableBytes()];

        in.readBytes(content);

        ProxyMessage proxyMessage = new ProxyMessage();
        proxyMessage.setChannelId(ctx.channel().id().asLongText());
        proxyMessage.setType(ProxyMessage.FORWARD);
        proxyMessage.setData(content);

        ServerChannelManager.bridgeChannelForward(proxyMessage);

        return null;

    }

}
